package it.ap.sa.acqua.dao.impl;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import it.ap.sa.acqua.dao.beans.SearchTankFilter;
import it.ap.sa.acqua.dao.model.TTank;
import it.ap.sa.core.dao.util.AbstractGenericEntityDao;
import it.ap.sa.core.utils.ListUtils;
import it.ap.sa.core.utils.LogUtil;
/**
 * @author Alessandro Paolillo
 */
@Repository
public class TTankDao  extends AbstractGenericEntityDao<TTank>{

	/**
	 * logger
	 */
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	/**
	 * @author Alessandro Paolillo
	 */
	@Transactional
	public TTank findByPk(long id) throws Exception{
		try{
			String  hql     = "from " + TTank.class.getName() + " where id = :id";
			Session session = this.getSessionFactory().getCurrentSession();
			Query   query   = session.createQuery(hql);

			query.setLong("id", id);

			return (TTank)query.uniqueResult();
		}catch(Exception e){
			if(logger.isDebugEnabled())
				logger.debug("Error in findByPk", e);
			throw e;
		}
	}
	/**
	 * @author Alessandro Paolillo
	 */
	public List<TTank> findByPks(List<Long> ids) throws Exception{
		try{
			String  hql     = "from " + TTank.class.getName() + " where id in (:ids)";
			Session session = this.getSessionFactory().getCurrentSession();
			Query   query   = session.createQuery(hql);

			query.setParameterList("ids", ids);

			return query.list();
		}catch(Exception e){
			if(logger.isDebugEnabled())
				logger.debug("Error in findByPks", e);
			throw e;
		}
	}
	
	/**
	 * @author Alessandro Paolillo
	 */
	public List<TTank> getTanks() throws Exception{
		try{
			String  hql     = "from " + TTank.class.getName();
			Session session = this.getSessionFactory().getCurrentSession();
			Query   query   = session.createQuery(hql);

			return query.list();
		}catch(Exception e){
			if(logger.isDebugEnabled())
				logger.debug("Error in getTanks", e);
			throw e;
		}
	}
	
	/**
	 * Questo metodo elimina una vasca dato l'id della vasca e l'id dell'utente che la possiede
	 * @param id
	 * @param idUser
	 * @return
	 * @throws Exception
	 */
	@Transactional
	public void deleteById(Long id, Long idUser) throws Exception {

		String    idLog     = "deleteById";
		StopWatch stopWatch = LogUtil.startStopWatch(idLog);
		logger.info(idLog);
		try {
			
			String sql = "DELETE FROM "+TTank.class.getName()+" WHERE id = :id AND idUser = :idUser";
			Session session = this.getSessionFactory().getCurrentSession();
			Query   query   = session.createQuery(sql);
			query.setLong("id"			,id);
			query.setLong("idUser"		,idUser);
			query.executeUpdate();
		} catch (Exception ex) {

			logger.error("Si è verificato un errore in deleteById: " + ex.getMessage() , ex);
			throw(ex);
		} finally{

			logger.info(LogUtil.endStopWatch(stopWatch));
		}
	}
	
	/**
	 * @author Alessandro Paolillo
	 * @param {@link TTank} tTank
	 * @throws Exception
	 */
	@Transactional
	public TTank saveOrUpdate(TTank tTank) throws Exception {

		String    idLog     = "saveOrUpdate";
		StopWatch stopWatch = LogUtil.startStopWatch(idLog);
		logger.info(idLog);
		try {
			
			saveOrUpdateEntity(tTank);
		} catch (Exception ex) {

			logger.error("Si è verificato un errore in saveOrUpdate: " + ex.getMessage() , ex);
			throw(ex);
		} finally{

			logger.info(LogUtil.endStopWatch(stopWatch));
		}
		return tTank;
	}
	
	/**
	 * @author Alessandro Paolillo
	 */
	public List<TTank> searchTank( SearchTankFilter filter) throws Exception{
		
		Session session = this.getSessionFactory().getCurrentSession();
		try{
			
			String  hql     = "from " + TTank.class.getName()+" ";
			if (filter!=null) {
				
				/** Set Filter **/	
				boolean isFirst = true;
				if ( filter.getAltezza()!=null  ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" altezza = :altezza ";
					isFirst = false;
				}
				if ( filter.getCapacita()!=null ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" capacita = :capacita ";
					isFirst = false;
				}
				if ( filter.getLarghezza()!=null  ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" larghezza = :larghezza ";
					isFirst = false;
				}
				if ( filter.getLunghezza()!=null  ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" lunghezza like :lunghezza ";
					isFirst = false;
				}
				if ( filter.getId()!=null ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" id = :id ";
					isFirst = false;
				}
				if ( filter.getUserId()!=null ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" idUser = :idUser ";
					isFirst = false;
				}
				if ( filter.getNome()!=null && !filter.getNome().equals("") ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" nome like :nome ";
					isFirst = false;
				}
			}
			Query   query   = session.createQuery(hql);
			
			if (filter!=null) {
				
				/** Set parameter **/
				if ( filter.getAltezza()!=null  )
					query.setDouble("altezza", filter.getAltezza());
				if ( filter.getCapacita()!=null )
					query.setDouble("capacita", filter.getCapacita());
				if ( filter.getLarghezza()!=null )
					query.setDouble("larghezza", filter.getLarghezza());
				if ( filter.getLunghezza()!=null )
					query.setDouble("lunghezza", filter.getLunghezza());
				if ( filter.getId()!=null )
					query.setLong("id", filter.getId());
				if ( filter.getUserId()!=null )
					query.setLong("idUser", Long.parseLong( filter.getUserId() ));
				if ( filter.getNome()!=null && !filter.getNome().equals("") )
					query.setString("nome", "%"+filter.getNome()+"%");
				
				/** Set paginator **/
				if ( filter.getiDisplayStart()!=-1 )
					query.setFirstResult( filter.getiDisplayStart() );
				if ( filter.getiDisplayLength()!=-1 )
					query.setMaxResults( filter.getiDisplayLength() );
			}
			return (List<TTank>)query.list();
		}catch(Exception e){
			if(logger.isDebugEnabled())
				logger.debug("Error in searchTank", e);
			throw e;
		}
	}
	
	/**
	 * @author Alessandro Paolillo
	 */
	public Long searchCountTank( SearchTankFilter filter) throws Exception{
		
		Session session = this.getSessionFactory().getCurrentSession();
		try{
			String  hql     = "from " + TTank.class.getName()+" ";
			if (filter!=null) {
				
				/** Set Filter **/	
				boolean isFirst = true;
				if ( filter.getAltezza()!=null  ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" altezza = :altezza ";
					isFirst = false;
				}
				if ( filter.getCapacita()!=null ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" capacita = :capacita ";
					isFirst = false;
				}
				if ( filter.getLarghezza()!=null  ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" larghezza = :larghezza ";
					isFirst = false;
				}
				if ( filter.getLunghezza()!=null  ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" lunghezza like :lunghezza ";
					isFirst = false;
				}
				if ( filter.getId()!=null ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" id = :id ";
					isFirst = false;
				}
				if ( filter.getUserId()!=null ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" idUser = :idUser ";
					isFirst = false;
				}
				if ( filter.getNome()!=null ) {
					hql += ( isFirst ? "WHERE" : "AND" ) +" nome = :nome ";
					isFirst = false;
				}
			}
			Query   query   = session.createQuery(hql);
			if (filter!=null) {
				
				/** Set parameter **/
				if ( filter.getAltezza()!=null  )
					query.setDouble("altezza", filter.getAltezza());
				if ( filter.getCapacita()!=null )
					query.setDouble("capacita", filter.getCapacita());
				if ( filter.getLarghezza()!=null )
					query.setDouble("larghezza", filter.getLarghezza());
				if ( filter.getLunghezza()!=null )
					query.setDouble("lunghezza", filter.getLunghezza());
				if ( filter.getId()!=null )
					query.setLong("id", filter.getId());
				if ( filter.getUserId()!=null )
					query.setLong("idUser", Long.parseLong( filter.getUserId() ));
				if ( filter.getNome()!=null )
					query.setString("nome", filter.getNome() );
			}
			List<TTank> list = (List<TTank>)query.list();
			if(ListUtils.listIsNotEmpty(list))
				return new Long ( list.size() );
			else 
				return new Long( 0 );
		}catch(Exception e){
			if(logger.isDebugEnabled())
				logger.debug("Error in searchCountTank", e);
			throw e;
		}
	}
}